#pragma once

namespace ShRp
{
	namespace Base
	{
		class Setting
		{
			// All private, only accessible by Base::Settings.
		private:
			Setting()
			{
				m_Value = 0;
			}
			struct Type
			{
				enum E
				{
					Color_t,
					Int, Int2, Int3, Int4,
					Float, Float2, Float3, Float4,
					Char, Char2, Char3, Char4,
					Short, Short2, Short3, Short4,
					String
				};
			};
			typedef std::map<std::string, Setting::Type::E> StringToSettingTypeMap;
			typedef std::pair<std::string, Setting::Type::E> StringToSettingTypePair;
			typedef std::map<Setting::Type::E, std::string> SettingTypeToStringMap;
			typedef std::pair<Setting::Type::E, std::string> SettingTypeToStringPair;
			static StringToSettingTypeMap m_StringToSettingTypeMap;
			static SettingTypeToStringMap m_SettingTypeToStringMap;


			friend class Settings;
			
			template<class U> U GetValue()
			{
				U val;
				memcpy_s(&val, sizeof(U), m_Value, sizeof(U));
				return val;
			}
			template<> std::string GetValue<std::string>()
			{
				// It's stored as a char*, so just return in in an std::string.
				return std::string(m_Value);
			}
			template<class U> void SetValue(const U& _Value, const Type::E _Type)
			{
				if(m_Value != NULL)
				{
					delete m_Value;
				}
				m_Value = (char*)malloc(sizeof(U));
				memcpy_s(m_Value, sizeof(U), &_Value, sizeof(U));

				m_Type = _Type;
			}
			template<> void SetValue<std::string>(const std::string& _Value, const Type::E _Type)
			{
				if(m_Value != NULL)
				{
					delete m_Value;
				}
				// Just store it as a char*.
				m_Value = (char*)malloc(_Value.length() + 1);
				strcpy_s(m_Value, _Value.length()+1, _Value.c_str());

				m_Type = _Type;
			}
			Setting::Type::E GetType()	{	return m_Type;	}
			
			char* m_Value;
			Setting::Type::E m_Type;
		};

		__declspec(selectany) Setting::StringToSettingTypeMap Setting::m_StringToSettingTypeMap;
		__declspec(selectany) Setting::SettingTypeToStringMap Setting::m_SettingTypeToStringMap;

		typedef std::pair<std::string, Setting*> StringSettingPair;
		typedef std::map <std::string, Setting*> StringSettingMap;
	};
};